/*
* 2010
* Authors: Sergey Lapin <lapanoid@gmail.com>, Kuznetsov Kirill<kirill.kuznets@gmail.com>
* Main cpp file
*/
#include "stdafx.h"

#include <fstream>
#include <boost/graph/graphviz.hpp>
#include <list>
#include <vector>
#include <iostream>
#include <conio.h>
#include <boost/graph/random.hpp>
#include <boost/random/uniform_real.hpp>
#include <boost/random/mersenne_twister.hpp>

#include <sstream> 
#include <string>

#define BOOST_GRAPH_READ_GRAPHVIZ_ITERATORS

using namespace std;

void create_random_graph(const size_t nV, const size_t nE)
{
    adjacency_list<vecS, vecS, directedS,vertex_p>  rnd_graph;
	rnd_graph.clear();
	boost::uniform_real<> ur(1,20);
	mt19937 rng;
	rng.seed(uint32_t(time(0)));
	generate_random_graph(rnd_graph, nV, nE, rng, false, false);
	stringstream tmp;
	tmp << nV << "-" << nE << ".dot";
	ofstream out;
	out.open(tmp.str().c_str());
	write_graphviz(out, rnd_graph);
	out.close();  
}

/*void cycle_test(const Graph &g)
{
	cout << "Have Cycle?: ";    
	cycle_detector vis;
	try {
		depth_first_search(g, visitor(vis));		
		cout << "No!";	
	} catch (has_cycle) {
		cout << "Yes!";
	}
	cout << endl;
}*/

bool cycle_test(const Graph &g)
{
	cout << "Have Cycle?: ";    
	bool haveCycle = FasGreedy::HaveCycle(g);
	if (haveCycle) {
		cout << "Yes!" << endl;    
	} else {
		cout << "No!" << endl;    
	}
	return haveCycle;	
}

int main()
{
	string input;
	clock_t start, end;    
	string inputfile, outputfile;

	do
	{
		Graph g;
		cout << "Enter dot file name with graph:" << endl;
		cin >> inputfile;          	

        try {
    		if (!fas_read(inputfile.c_str(), g)) {
			    while (!_kbhit());    
			    return 0;
		    }
        } catch (bad_parallel_edge) {	
            cout << "Error!!!" << 
            endl << "Exeption name: bad_parallel_edge" << endl;
            continue;
	    } catch (directed_graph_error) {	
            cout << "Error!!!" << 
            endl << "Exeption name: directed_graph_error" << endl;
            continue;
	    } catch (undirected_graph_error) {	
            cout << "Error!!!" << 
            endl << "Exeption name: undirected_graph_error" << endl;
            continue;
        }
		
		cout << "Done!" << endl; 

		cout << "Vertex_num:" << num_vertices(g) << " "; 
		cout << "Edge_num:" << num_edges(g) << endl;
		int init_edges =  num_edges(g);
		cycle_test(g);

		cout << "If Greedy press 1, if genetic press 2" << endl;

		char algo;
		cin >> algo; 

		switch(algo)
		{
		case '1':
			cout << "Greedy algorithm:" << endl;
			start = clock();
			FasGreedy::MakeAcyclicGreedy(g);
			end = clock();
			break;
		case '2':        
			int size, max_iters;
			cout << "Genetic algorithm:" << endl;
			do {
				cout << "Enter generation size (>0) :" << endl;
				cin >> size;
			} while(size <= 0);
			do {
				cout << "Enter max number of iterations (>0) :" << endl;
				cin >> max_iters;	
			} while(max_iters <= 0);
			start = clock();
			FasGenetic::RemoveCycles(g, (size_t) size, (size_t) max_iters);
			end = clock();
			break;
		default:
			cout << "wrong algorithm" << endl;
			return 0;
		}

		cout << "Running time is: ";
		cout << (double)(end - start) / CLOCKS_PER_SEC << " seconds." << endl;
		int fin_edges = num_edges(g);
		cout << init_edges - fin_edges << " edges deleted" << endl<< fin_edges<<" edges_left\n";
		cycle_test(g);

		//write given graph to the dot file
		stringstream tmp;
		tmp << inputfile.c_str() << "out.dot";
		fas_write(tmp.str(), g);
		cout << "Press any key...";

		cout << "Press \"q\" for quit, or any other key for next test" << endl;
		cin >> input;
	} while (input != "q");

	return 0; 
}